import random
import copy
from board import Board
from Monte_TreeSerach import Node, Monte_tree, UCB
import operator

# 定义蒙特卡洛树里的节点状态转移方程
def state_after_action(action, type, state):

    state1 = copy.deepcopy(state)

    # 表示这一局不落子
    if action is None:
        return state1
    color = 'X' if type == 'min' else 'O'

    # 得到落子后的新棋盘状态
    state1._move(action=action, color=color)
    return state1

# 定义蒙特卡洛树里的可行action搜索方程
def find_all_next(current):
    color = 'X' if current.type == 'min' else 'O'
    anti_color = 'O' if current.type == 'min' else 'X'

    # 当前状态下棋方可行选择
    l = list(current.state.get_legal_actions(color))
    # 对方的可行选择
    l_op = list(current.state.get_legal_actions(anti_color))
    # 下棋方只能跳过的情况
    if len(l) == 0 and len(l_op) > 0:
        return [None]
    # 下棋方下子
    if len(l) > 0:
        return l
    # 游戏结束的情况
    return None

# 定义蒙特卡洛树里的奖励函数
def get_reward(current):
    w, _ = current.state.get_winner()
    if w == 0:
        # 黑棋赢
        return 1
    if w == 1:
        # 白棋赢
        return 0
    if w == 2:
        # 平局
        return 0.5
    

class AIPlayer(object):
    def __init__(self, color):
        # AI 方的颜色
        self.color = color
        # 蒙特卡洛树
        self.tree = None
        # 当前棋盘
        self.board = None

    # 寻找蒙特卡洛树根节点的子节点中棋盘board对应的节点(若无则创建),将其变成根节点.
    def change_root(self,board):
        for child in self.tree.root[0].children:
            if operator.eq(child.state._board,board._board):
                self.tree.root.pop()
                self.tree.root.append(child)
                child.parent = None
                self.tree.currents.pop()
                self.tree.currents.append(child)
                self.tree.all_visit = child.visit
                return True
        self.tree.root[0].append_child(board=board)
        for child in self.tree.root[0].children:
            if operator.eq(child.state._board,board._board):

                self.tree.root.pop()
                self.tree.root.append(child)
                child.parent = None
                self.tree.currents.pop()
                self.tree.currents.append(child)
                self.tree.all_visit = child.visit
                return True
        return False

    # 初始化蒙特卡洛树
    def generate_tree(self):
        if self.tree is None:
            type = 'min' if self.color == 'X' else 'max'
            self.tree = Monte_tree(ori_state=self.board, state_after_action=state_after_action, find_all_next=find_all_next,
                                   get_reward=get_reward, C=0.7, type=type)
            return True
        else:
            self.change_root(self.board)
        return False

    def get_result(self):
        self.generate_tree()

        # UCTSearch进行蒙特卡洛搜索,最后的current[0]变成action对应的子节点.
        action = self.tree.UCTSearch(time_limit=1)
        self.change_root(self.tree.currents[0].state)
        return action

    def get_move(self, board):
        # 复制一个副本
        self.board = copy.deepcopy(board)
        self.generate_tree()

        # UCTSearch进行蒙特卡洛搜索,最后的current[0]变成action对应的子节点.
        action = self.tree.UCTSearch(time_limit=1)
        self.change_root(self.tree.currents[0].state)
        return action
# class AIPlayer:
#     """
#     AI 玩家
#     """

#     def __init__(self, color):
#         """
#         玩家初始化
#         :param color: 下棋方，'X' - 黑棋，'O' - 白棋
#         """

#         self.color = color

#     def get_move(self, board):
#         """
#         根据当前棋盘状态获取最佳落子位置
#         :param board: 棋盘
#         :return: action 最佳落子位置, e.g. 'A1'
#         """
#         if self.color == 'X':
#             player_name = '黑棋'
#         else:
#             player_name = '白棋'
#         print("请等一会，对方 {}-{} 正在思考中...".format(player_name, self.color))

#         # -----------------请实现你的算法代码--------------------------------------

#         action = None
#         # ------------------------------------------------------------------------

#         return action
